package com.syjy.tunnelworker.senders.iml;

import com.syjy.DataExchangeException;
import com.syjy.container.ProtocolDataContainer;
import com.syjy.tunnelinfo.DataPoint;
import com.syjy.tunnelinfo.TunnelStatus;
import com.syjy.tunnelinfo.sendertunnelinfo.SenderModbusTcpTunnelInfo;
import com.syjy.tunnelworker.BaseProtocolTunnel;
import com.syjy.tunnelworker.senders.DataSenderInterface;
import com.syjy.tunnelworker.workassist.SingleThreadPoolExecutorUtil;
import wei.yigulu.modbus.domain.datatype.BooleanModbusDataInRegister;
import wei.yigulu.modbus.domain.datatype.ModbusDataTypeEnum;
import wei.yigulu.modbus.domain.datatype.NumericModbusData;
import wei.yigulu.modbus.netty.ModbusTcpSlaverBuilder;

import java.math.BigDecimal;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * modbus 转发数据通道
 *
 * @author 修唯xiuwei
 * @version 3.0
 */
public class ModbusTcpDataSender extends AbstractModbusDataSender<SenderModbusTcpTunnelInfo,ModbusTcpSlaverBuilder> implements DataSenderInterface {



	/**
	 * 顶层的构造方法
	 *
	 * @param tunnelInfo 通道信息
	 */
	public ModbusTcpDataSender(SenderModbusTcpTunnelInfo tunnelInfo) {
		super(tunnelInfo);
	}

	@Override
	public ModbusTcpDataSender buildTunnel() throws DataExchangeException {
		protocolBuilder = new MyModbusTcpSlaver(this.tunnelInfo.getSelfPort());
		protocolBuilder.setLog(this.log);
		this.setTunnelStatus(TunnelStatus.BUILT);
		getProtocolTunnelContainer().addTunnel(this);
		setSlaveId(this.tunnelInfo.getSlaveId());
		setModbusSlaveDataContainer(protocolBuilder.getModbusSlaveDataContainer());
		if (this.tunnelInfo.getFunctionCode() == 1 || this.tunnelInfo.getFunctionCode() == 2) {
			setFunctionFlag(0);
		} else {
			setFunctionFlag(1);
		}
		parseGatherDataPoint();
		log.info("成功创建ModbusTCPSlaver通道对象：{}", this.tunnelInfo.getTunnelName());
		return this;
	}



	@Override
	public ModbusTcpDataSender startTunnel() throws DataExchangeException {
		log.info("modbus TCP slaver {} 通道开始连接", getTunnelInfo().getTunnelName());
		protocolTunnelContainer.addUpdateDateTask(this);
		try {
			SingleThreadPoolExecutorUtil.executeBySingleThreadExecutor(() -> {
				try {
					this.protocolBuilder.create();
					log.error("Modbus TCP slaver  创建通道失败");
					setTunnelStatus(TunnelStatus.LISTENPORTFAIL);
				} catch (Exception e) {
					log.error("Modbus TCP slaver  创建通道失败", e);
					setTunnelStatus(TunnelStatus.LISTENPORTFAIL);
				}
			});
		} catch (Exception e) {
			log.error("Modbus TCP slaver 创建通道失败", e);
			setTunnelStatus(TunnelStatus.LISTENPORTFAIL);
			throw new DataExchangeException(10007, "Modbus TCP slaver创建通道失败");
		}
		if (!TunnelStatus.LISTENPORTFAIL.equals(getTunnelStatus())) {
			setTunnelStatus(TunnelStatus.LISTENPORTSUCCESS);
		}
		return this;
	}


	@Override
	public BaseProtocolTunnel tunnelStop() throws DataExchangeException {
		if (this.protocolBuilder != null) {
			this.protocolBuilder.stop();
		}
		log.info("关闭 Modbus TCP slaver 通道 {}", this.tunnelInfo.getTunnelName());
		return super.tunnelStop();
	}


	@Override
	public void updateData2Protocol() throws DataExchangeException {
		if (this.protocolBuilder.getChannels().size() == 0) {
			log.trace("当前没有master联入");
			setTunnelStatus(TunnelStatus.LISTENPORTSUCCESSANDNOCONN);
			return;
		}
		super.updateData2Protocol();
	}

	class MyModbusTcpSlaver extends ModbusTcpSlaverBuilder{

		public MyModbusTcpSlaver(int port) {
			super(port);
		}

		public void connected(InetSocketAddress ipSocket) {
			setTunnelStatus(TunnelStatus.LISTENPORTSUCCESSANDCONN);
		}


	}

}
